package com.tonann.app.service.impl;

import com.tonann.app.VO.DeviceDashboardVO;
import com.tonann.app.VO.MySensor;
import com.tonann.app.domain.*;
import com.tonann.app.mapper.AppDeviceMapper;
import com.tonann.app.mapper.AppDevicePlacesMapper;
import com.tonann.app.mapper.AppSensorMapper;
import com.tonann.app.service.IAppDeviceService;
import com.tonann.app.service.IAppGatewayService;
import com.tonann.app.service.IAppSensorService;
import com.tonann.app.utils.DeviceUtils;
import com.tonann.common.constant.CacheConstants;
import com.tonann.common.constant.UserConstants;
import com.tonann.common.core.domain.entity.SysPlace;
import com.tonann.common.core.domain.entity.SysRole;
import com.tonann.common.core.domain.entity.SysUser;
import com.tonann.common.core.redis.RedisCache;
import com.tonann.common.core.text.Convert;
import com.tonann.common.exception.ServiceException;
import com.tonann.common.utils.DateUtils;
import com.tonann.common.utils.SecurityUtils;
import com.tonann.common.utils.StringUtils;
import com.tonann.common.utils.spring.SpringUtils;
import com.tonann.system.service.ISysUserService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 运行设备Service业务层处理
 *
 * @author tonann
 * @date 2022-10-12
 */
@Service
public class AppDeviceServiceImpl implements IAppDeviceService {

    @Resource
    private AppDeviceMapper appDeviceMapper;
    @Resource
    private ISysUserService systemUserService;
    @Resource
    private RedisCache redisCache;
    @Resource
    private IAppGatewayService appGatewayService;
    @Resource
    private AppSensorMapper appSensorMapper;

    @Resource
    private IAppSensorService appSensorService;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private AppDevicePlacesMapper devicePlacesMapper;
    /**
     * 全部数据权限
     */
    public static final String DATA_SCOPE_ALL = "1";

    /**
     * 自定数据权限
     */
    public static final String DATA_SCOPE_CUSTOM = "2";

    /**
     * 部门数据权限
     */
    public static final String DATA_SCOPE_DEPT = "3";

    /**
     * 部门及以下数据权限
     */
    public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";

    /**
     * 空间位置数据权限
     */
    public static final String DATA_SCOPE_PLACE = "3";

    /**
     * 空间位置及以下数据权限
     */
    public static final String DATA_SCOPE_PLACE_AND_CHILD = "4";

    /**
     * 仅本人数据权限
     */
    public static final String DATA_SCOPE_SELF = "5";

    /**
     * 数据权限过滤关键字
     */
    public static final String DATA_SCOPE = "dataScope";

    /**
     * 查询运行设备
     *
     * @param deviceId 运行设备主键
     * @return 运行设备
     */
    @Override
    public AppDevice selectAppDeviceByDeviceId(Long deviceId) {
        AppDevice appDevice = DeviceUtils.getDeviceByDeviceId(deviceId);
        if (StringUtils.isNull(appDevice)) {
            appDevice = appDeviceMapper.selectAppDeviceByDeviceId(deviceId);
            if (appDevice != null) {
                AppGateway gateway = appGatewayService.selectAppGatewayByGatewayId(appDevice.getGatewayId());
                appDevice.setAppGateway(gateway);
                DeviceUtils.setDeviceByDeviceId(appDevice);
            }
        }
        return appDevice;
    }

    /**
     * 查询运行设备列表
     *
     * @param appDevice 运行设备
     * @return 运行设备
     */
    @Override
    public List<AppDevice> selectAppDeviceList(AppDevice appDevice) {
        List<AppDevice> list = appDeviceMapper.selectAppDeviceList(appDevice);
//        List<Long> allAdmin = selectAppDeviceAdminListByDeviceId(null);
//        List<Long> allOperator = selectAppDeviceOperatorListByDeviceId(null);
//        List<Long> ids = Stream.of(allAdmin, allOperator).flatMap(Collection::stream).distinct().collect(Collectors.toList());
//        Map<Long, SysUser> userMap = new HashMap<>();
//        if (!ids.isEmpty()) {
//            List<SysUser> userList = systemUserService.selectUserByIds(ids);
//            for (SysUser user : userList) {
//                userMap.put(user.getUserId(), user);
//            }
//        }
//        for (AppDevice device : list) {
//            if (device.getAdminIds() != null && device.getAdminIds().length > 0) {
//                List<SysUser> admin = new ArrayList<>();
//                for (Long id : device.getAdminIds()) {
//                    SysUser user = userMap.get(id);
//                    if (user != null) {
//                        admin.add(user);
//                    }
//                }
//                device.setAdmin(admin);
//            }
//            if (device.getOperatorIds() != null && device.getOperatorIds().length > 0) {
//                List<SysUser> operator = new ArrayList<>();
//                for (Long id : device.getOperatorIds()) {
//                    SysUser user = userMap.get(id);
//                    if (user != null) {
//                        operator.add(user);
//                    }
//                }
//                device.setOperator(operator);
//            }
//        }

//        for (AppDevice device : list) {
//            List<Long> adminIds = selectAppDeviceAdminListByDeviceId(device.getDeviceId());
//            List<Long> operatorIds = selectAppDeviceOperatorListByDeviceId(device.getDeviceId());
//            List<Long> ids = Stream.of(adminIds,operatorIds).flatMap(Collection::stream).distinct().collect(Collectors.toList());
//            Map<Long,SysUser> userMap = new HashMap<>();
//            if(!ids.isEmpty()){
//                List<SysUser> userList = systemUserService.selectUserByIds(ids);
//                for(SysUser user : userList){
//                    userMap.put(user.getUserId(),user);
//                }
//            }
//            if (!adminIds.isEmpty()) {
//                List<SysUser> admin = new ArrayList<>();
//                for (Long id : adminIds) {
//                    SysUser user = userMap.get(id);
//                    if (user != null) {
//                        admin.add(user);
//                    }
//                }
//                device.setAdmin(admin);
//            }
//            if (!operatorIds.isEmpty()) {
//                List<SysUser> operator = new ArrayList<>();
//                for (Long id : operatorIds) {
//                    SysUser user = userMap.get(id);
//                    if (user != null) {
//                        operator.add(user);
//                    }
//                }
//                device.setOperator(operator);
//            }
//        }
        return list;
    }

    /**
     * 新增运行设备
     *
     * @param appDevice 运行设备
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AppDevice insertAppDevice(AppDevice appDevice) throws Exception {
        if (appDevice.getParentId() > 0) {
            AppDevice info = appDeviceMapper.selectAppDeviceByDeviceId(appDevice.getParentId());
            // 如果父节点不为正常状态,则不允许新增子节点
            if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) {
                throw new ServiceException("设备停用，不允许新增");
            }

            String ancestors = info.getAncestors() + "," + info.getDeviceId();
            appDevice.setAncestors(ancestors);
            Long count = info.getSubCount();
            if (count == null) {
                info.setSubCount(1L);
            } else {
                info.setSubCount(count + 1L);
            }
            Long diffPower = 0L;
            if (appDevice.getRatedPower() != null) {
//              Long ratedPower =  info.getRatedPower();
//              if (ratedPower != null){
//                  info.setRatedPower(ratedPower + appDevice.getRatedPower());
//              }else {
//                  info.setRatedPower(appDevice.getRatedPower());
//              }
                List<AppDevice> child = appDeviceMapper.selectChildrenAppDeviceById(info.getDeviceId());
                Long totalPower = appDevice.getRatedPower();
                for (AppDevice d : child) {
                    Long ratedPower = d.getRatedPower();
                    if (ratedPower != null) {
                        totalPower += ratedPower;
                    }
                }
                diffPower = totalPower - info.getRatedPower();
                info.setRatedPower(totalPower);
            }
            info.setUpdateTime(DateUtils.getNowDate());
            appDeviceMapper.updateAppDevice(info);
            if (ancestors.contains(",")) {
                String[] strs = ancestors.split(",");
                for (String str : strs) {
                    BigDecimal bigDecimal = new BigDecimal(str);
                    if (bigDecimal.intValue() > 0) {
                        AppDevice device = appDeviceMapper.selectAppDeviceByDeviceId(bigDecimal.longValue());
                        if (device != null) {
                            device.setRatedPower(device.getRatedPower() + diffPower);
                            appDeviceMapper.updateAppDevice(device);
                        }
                    }
                }
            }
        } else {
            appDevice.setAncestors(appDevice.getParentId().toString());
        }
        appDevice.setCreateTime(DateUtils.getNowDate());
        appDevice.setUpdateTime(DateUtils.getNowDate());
        if (!checkAppDeviceNameUnique(appDevice).equals(UserConstants.UNIQUE)){
            throw new Exception("传感器名称重复");
        }
        if (!checkAppDeviceCodeUnique(appDevice).equals(UserConstants.UNIQUE)){
            throw new Exception("传感器编号重复");
        }
        int row = appDeviceMapper.insertAppDevice(appDevice);
        if (row > 0) {
            DeviceUtils.setDeviceByDeviceId(appDevice);
        }

        if (appDevice.getAdminIds() != null && appDevice.getAdminIds().length > 0) {

            for (int i = 0; i < appDevice.getAdminIds().length; i++) {
                Long id = appDevice.getAdminIds()[i];
                appDeviceMapper.insertAppDeviceAdmin(appDevice.getDeviceId(), id);
                MySensor.getInstance().userDeviceMap.remove(id);
            }
        }
        if (appDevice.getOperatorIds() != null && appDevice.getOperatorIds().length > 0) {
            for (int i = 0; i < appDevice.getOperatorIds().length; i++) {
                Long id = appDevice.getOperatorIds()[i];
                appDeviceMapper.insertAppDeviceOperator(appDevice.getDeviceId(), id);
                MySensor.getInstance().userDeviceMap.remove(id);
            }
        }
        if (appDevice.getDeptIds() != null){
            for (Long deptId : appDevice.getDeptIds()){
                appDeviceMapper.insertAppDeviceDept(appDevice.getDeviceId(),deptId);
            }
        }

        if (appDevice.getPlaceIds() != null){
            for (Long placeId : appDevice.getPlaceIds()){
                appDeviceMapper.insertAppDevicePlace(appDevice.getDeviceId(),placeId);
            }
        }
        return appDevice;
    }

    /**
     * 修改运行设备
     *
     * @param appDevice 运行设备
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateAppDevice(AppDevice appDevice) throws Exception {
        appDevice.setUpdateTime(DateUtils.getNowDate());
        if (!checkAppDeviceNameUnique(appDevice).equals(UserConstants.UNIQUE)){
            throw new Exception("传感器名称重复");
        }
        if (!checkAppDeviceCodeUnique(appDevice).equals(UserConstants.UNIQUE)){
            throw new Exception("传感器编号重复");
        }
        AppDevice oldDevice = appDeviceMapper.selectAppDeviceByDeviceId(appDevice.getDeviceId());
        AppDevice newParentDevice = appDeviceMapper.selectAppDeviceByDeviceId(appDevice.getParentId());
        if (StringUtils.isNotNull(newParentDevice) && StringUtils.isNotNull(oldDevice)) {
            String newAncestors = newParentDevice.getAncestors() + "," + newParentDevice.getDeviceId();
            String oldAncestors = oldDevice.getAncestors();
            appDevice.setAncestors(newAncestors);
            updateDeviceChildren(appDevice.getDeviceId(), newAncestors, oldAncestors);
        }
        Long diffPower = 0L;
        diffPower = appDevice.getRatedPower() - oldDevice.getRatedPower();
        String ancestors = oldDevice.getAncestors();
        if (ancestors.contains(",")) {
            String[] strs = ancestors.split(",");
            for (String str : strs) {
                if (!str.isEmpty()) {
                    BigDecimal bigDecimal = new BigDecimal(str);
                    if (bigDecimal.intValue() > 0) {
                        AppDevice device = appDeviceMapper.selectAppDeviceByDeviceId(bigDecimal.longValue());
                        if (device != null) {
                            device.setRatedPower(device.getRatedPower() + diffPower);
                            appDeviceMapper.updateAppDevice(device);
                        }
                    }
                }
            }
        }
        appDeviceMapper.deleteAppDeviceAdminByDeviceId(appDevice.getDeviceId());
        appDeviceMapper.deleteAppDeviceOperatorByDeviceId(appDevice.getDeviceId());
        List<Long> ids = new ArrayList<>();
        if (appDevice.getAdminIds() != null && appDevice.getAdminIds().length > 0) {
            for (int i = 0; i < appDevice.getAdminIds().length; i++) {
                Long id = appDevice.getAdminIds()[i];
                appDeviceMapper.insertAppDeviceAdmin(appDevice.getDeviceId(), id);
                MySensor.getInstance().userDeviceMap.remove(id);
                ids.add(id);
            }
        }
        redisCache.deleteObject("AppDeviceAdminListByDeviceId:" + appDevice.getDeviceId());
        redisCache.deleteObject("AppDeviceOperatorListByDeviceId:" + appDevice.getDeviceId());
//        redisTemplate.opsForValue().set("AppDeviceAdminListByDeviceId:" + appDevice.getDeviceId(),ids);
        List<Long> ids1 = new ArrayList<>();
        if (appDevice.getOperatorIds() != null && appDevice.getOperatorIds().length > 0) {
            for (int i = 0; i < appDevice.getOperatorIds().length; i++) {
                Long id = appDevice.getOperatorIds()[i];
                appDeviceMapper.insertAppDeviceOperator(appDevice.getDeviceId(), id);
                MySensor.getInstance().userDeviceMap.remove(id);
                ids1.add(id);
            }
        }
//        redisTemplate.opsForValue().set("AppDeviceOperatorListByDeviceId:" + appDevice.getDeviceId(),ids1);
        int row = appDeviceMapper.updateAppDevice(appDevice);
        if (row > 0) {
            DeviceUtils.setDeviceByDeviceId(appDevice);
        }
        return row;
    }

    /**
     * 修改子元素关系
     *
     * @param deviceId     被修改的设备ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateDeviceChildren(Long deviceId, String newAncestors, String oldAncestors) {
        List<AppDevice> children = appDeviceMapper.selectChildrenAppDeviceById(deviceId);
        for (AppDevice child : children) {
            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
            updateDeviceChildren(child.getDeviceId(), newAncestors, oldAncestors);
        }
        if (!children.isEmpty()) {
            appDeviceMapper.updateAppDeviceChildren(children);
        }
    }

    /**
     * 修改运行设备
     *
     * @param appDevice 运行设备
     * @return 结果
     */
    @Override
    public int updateAppDeviceStatus(AppDevice appDevice) {
        String s = appDevice.getIsRunning();
        if (s != null) {
            if (StringUtils.endsWith(s, ".0")) {
                String val = StringUtils.substringBefore(s, ".0");
                appDevice.setIsRunning(val);
            }
        }
        s = appDevice.getIsException();
        if (s != null) {
            if (StringUtils.endsWith(s, ".0")) {
                String val = StringUtils.substringBefore(s, ".0");
                appDevice.setIsException(val);
            }
        }
        s = appDevice.getIsOnline();
        if (s != null) {
            if (StringUtils.endsWith(s, ".0")) {
                String val = StringUtils.substringBefore(s, ".0");
                appDevice.setIsOnline(val);
            }
        }
        if (appDevice.getIsRunning() != null && appDevice.getIsRunning().equals("true")) {
            appDevice.setIsRunning("1");
        } else if (appDevice.getIsRunning() != null && appDevice.getIsRunning().equals("false")) {
            appDevice.setIsRunning("0");
        }
        if (appDevice.getIsException() != null && appDevice.getIsException().equals("true")) {
            appDevice.setIsException("1");
        } else if (appDevice.getIsException() != null && appDevice.getIsException().equals("false")) {
            appDevice.setIsException("0");
        }
        if (appDevice.getIsOnline() != null && appDevice.getIsOnline().equals("true")) {
            appDevice.setIsOnline("1");
        } else if (appDevice.getIsOnline() != null && appDevice.getIsOnline().equals("false")) {
            appDevice.setIsOnline("0");
        }
        appDevice.setParentId(null);
        appDevice.setGatewayId(null);
        appDevice.setProjectId(null);
        appDevice.setDeviceCode(null);
        appDevice.setDeviceName(null);
        appDevice.setSubCount(null);
        appDevice.setRatedPower(null);
        appDevice.setStatus(null);
        appDevice.setType(null);
        appDevice.setIsShow(null);
        appDevice.setBrand(null);
        appDevice.setManufactor(null);
        appDevice.setModel(null);
        appDevice.setAcquisitionDate(null);
        appDevice.setMaintenanceUnit(null);
        appDevice.setMaintenanceDate(null);
        appDevice.setAncestors(null);
        appDevice.setCreateTime(null);
        appDevice.setUpdateTime(null);
        int row = appDeviceMapper.updateAppDevice(appDevice);
        if (row > 0) {
            appDevice = appDeviceMapper.selectAppDeviceByDeviceId(appDevice.getDeviceId());
            DeviceUtils.setDeviceByDeviceId(appDevice);
        }
        return row;
    }

    /**
     * 批量删除运行设备
     *
     * @param deviceIds 需要删除的运行设备主键
     * @return 结果
     */
    @Override
    public int deleteAppDeviceByDeviceIds(Long[] deviceIds) {
        int row = appDeviceMapper.deleteAppDeviceByDeviceIds(deviceIds);
        if (row > 0) {
            for (Long id : deviceIds) {
//                DeviceUtils.removeDeviceCache(id.toString());
                deleteAppDeviceByDeviceId(id);
            }
        }
        return row;
    }

    /**
     * 删除运行设备信息
     *
     * @param deviceId 运行设备主键
     * @return 结果
     */
    @Override
    public int deleteAppDeviceByDeviceId(Long deviceId) {
        AppDevice appDevice = this.selectAppDeviceByDeviceId(deviceId);
        AppDevice info = appDeviceMapper.selectAppDeviceByDeviceId(appDevice.getParentId());
        if (info != null) {
            // 如果父节点不为正常状态,则不允许删除节点
            if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) {
                throw new ServiceException("设备停用，不允许删除");
            }
            Long count = info.getSubCount();
            if (count == null) {
                info.setSubCount(0L);
            } else {
                info.setSubCount(count - 1L);
            }
            Long diffPower = 0L;
            if (appDevice.getRatedPower() != null) {
                diffPower = appDevice.getRatedPower();
                info.setRatedPower(info.getRatedPower() - diffPower);
                String ancestors = info.getAncestors();
                if (ancestors.contains(",")) {
                    String[] strs = ancestors.split(",");
                    for (String str : strs) {
                        BigDecimal bigDecimal = new BigDecimal(str);
                        if (bigDecimal.intValue() > 0) {
                            AppDevice device = appDeviceMapper.selectAppDeviceByDeviceId(bigDecimal.longValue());
                            if (device != null) {
                                device.setRatedPower(device.getRatedPower() - diffPower);
                                appDeviceMapper.updateAppDevice(device);
                            }
                        }
                    }
                }
            }
            info.setUpdateTime(DateUtils.getNowDate());
            info.setUpdateBy(SecurityUtils.getUsername());
//        appDeviceMapper.updateAppDevice(info);
        }

        List<Long> adminIds =  appDeviceMapper.selectAppDeviceAdminListByDeviceId(deviceId);
        for (Long  id : adminIds){
            MySensor.getInstance().userDeviceMap.remove(id);
        }
        List<Long> operatorIds =  appDeviceMapper.selectAppDeviceOperatorListByDeviceId(deviceId);
        for (Long  id : operatorIds){
            MySensor.getInstance().userDeviceMap.remove(id);
        }

        appDeviceMapper.deleteAppDeviceDeptByDeviceId(deviceId);
        appDeviceMapper.deleteAppDevicePlaceByDeviceId(deviceId);
        appDeviceMapper.deleteAppDeviceAdminByDeviceId(deviceId);
        appDeviceMapper.deleteAppDeviceOperatorByDeviceId(deviceId);
        appSensorService.deleteAppSensorByDeviceId(deviceId);
        redisCache.deleteObject("AppDeviceAdminListByDeviceId:" + deviceId);
        redisCache.deleteObject("AppDeviceOperatorListByDeviceId:" + deviceId);
        int row = appDeviceMapper.deleteAppDeviceByDeviceId(deviceId);
        if (row > 0) {
            DeviceUtils.removeDeviceCache(deviceId.toString());
        }
        return row;
    }

    @Override
    public List<AppTreeSelect> selectAppDeviceTreeList(AppDevice appDevice) {
        List<AppDevice> devices = SpringUtils.getAopProxy(this).selectAppDeviceList(appDevice);
        return buildAppDeviceTreeSelect(devices);
    }

    @Override
    public List<AppDevice> buildAppDeviceTree(List<AppDevice> appDevices) {
        List<AppDevice> returnList = new ArrayList<AppDevice>();
        List<Long> tempList = new ArrayList<Long>();
        for (AppDevice device : appDevices) {
            tempList.add(device.getDeviceId());
        }
        for (AppDevice device : appDevices) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(device.getParentId())) {
                recursionFn(appDevices, device);
                returnList.add(device);
            }
        }
        if (returnList.isEmpty()) {
            returnList = appDevices;
        }
        return returnList;
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<AppDevice> list, AppDevice t) {
        // 得到子节点列表
        List<AppDevice> childList = getChildList(list, t);
        t.setChildren(childList);
        for (AppDevice tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }


    /**
     * 得到子节点列表
     */
    private List<AppDevice> getChildList(List<AppDevice> list, AppDevice t) {
        List<AppDevice> tlist = new ArrayList<AppDevice>();
        Iterator<AppDevice> it = list.iterator();
        while (it.hasNext()) {
            AppDevice n = (AppDevice) it.next();
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getParentId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<AppDevice> list, AppDevice t) {
        return getChildList(list, t).size() > 0;
    }

    @Override
    public List<AppTreeSelect> buildAppDeviceTreeSelect(List<AppDevice> appDevices) {
        List<AppDevice> appDeviceTrees = buildAppDeviceTree(appDevices);
        return appDeviceTrees.stream().map(AppTreeSelect::new).collect(Collectors.toList());
    }

    @Override
    public List<Long> selectAppDeviceDeptListByDeviceId(Long deviceId) {
        AppDevice device = appDeviceMapper.selectAppDeviceByDeviceId(deviceId);
        return appDeviceMapper.selectAppDeviceDeptListByDeviceId(deviceId, device.isDeptCheckStrictly());
    }


    @Override
    public List<Long> selectAppDevicePlaceListByDeviceId(Long deviceId) {
        AppDevice device = appDeviceMapper.selectAppDeviceByDeviceId(deviceId);
        return appDeviceMapper.selectAppDevicePlaceListByDeviceId(deviceId, device.isPlaceCheckStrictly());
    }

    @Override
    public List<Long> selectAppDeviceAdminListByDeviceId(Long deviceId) {
//        List<Long> ids =  (List<Long>) redisTemplate.opsForValue().get("AppDeviceAdminListByDeviceId:" + deviceId);
        List<Long> ids = (List<Long>) redisCache.getCacheObject("AppDeviceAdminListByDeviceId:" + deviceId);
        if (ids == null) {
            ids = appDeviceMapper.selectAppDeviceAdminListByDeviceId(deviceId);
//            redisTemplate.opsForValue().set("AppDeviceAdminListByDeviceId:" + deviceId,ids);
            redisCache.setCacheObject("AppDeviceAdminListByDeviceId:" + deviceId, ids);
        }
        return ids;
    }

    @Override
    public List<Long> selectAppDeviceOperatorListByDeviceId(Long deviceId) {
//        List<Long> ids =  (List<Long>) redisTemplate.opsForValue().get("AppDeviceOperatorListByDeviceId:" + deviceId);
        List<Long> ids = (List<Long>) redisCache.getCacheObject("AppDeviceOperatorListByDeviceId:" + deviceId);
        if (ids == null) {
            ids = appDeviceMapper.selectAppDeviceOperatorListByDeviceId(deviceId);
//            redisTemplate.opsForValue().set("AppDeviceOperatorListByDeviceId:" + deviceId,ids);
            redisCache.setCacheObject("AppDeviceOperatorListByDeviceId:" + deviceId, ids);
        }
        return ids;
    }

    @Override
    public int selectNormalChildrenAppDeviceById(Long appDeviceId) {
        return appDeviceMapper.selectNormalChildrenAppDeviceById(appDeviceId);
    }

    @Override
    public boolean hasChildByAppDeviceId(Long appDeviceId) {
        int result = appDeviceMapper.hasChildByAppDeviceId(appDeviceId);
        return result > 0;
    }

    @Override
    public boolean checkAppDeviceExistUser(Long appDeviceId) {
        int result = appDeviceMapper.checkAppDeviceExistUser(appDeviceId);
        return result > 0;
    }

    @Override
    public String checkAppDeviceNameUnique(AppDevice appDevice) {
        Long deviceId = StringUtils.isNull(appDevice.getDeviceId()) ? -1L : appDevice.getDeviceId();
        AppDevice info = appDeviceMapper.checkAppDeviceNameUnique(appDevice.getDeviceName(), appDevice.getParentId());
        if (StringUtils.isNotNull(info) && info.getDeviceId().longValue() != deviceId.longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    public String checkAppDeviceCodeUnique(AppDevice appDevice) {
        Long deviceId = StringUtils.isNull(appDevice.getDeviceId()) ? -1L : appDevice.getDeviceId();
        AppDevice info = appDeviceMapper.checkAppDeviceCodeUnique(appDevice.getDeviceCode());
        if (StringUtils.isNotNull(info) && info.getDeviceId().longValue() != deviceId.longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    @Override
    public void checkDeviceDataScope(Long deviceId) {

        if (!SysUser.isAdmin(SecurityUtils.getUserId())) {
            AppDevice device = new AppDevice();
            device.setDeviceId(deviceId);
            List<AppDevice> devices = SpringUtils.getAopProxy(this).selectAppDeviceList(device);
            if (StringUtils.isEmpty(devices)) {
                throw new ServiceException("没有权限访问设备数据！");
            }
        }
    }

    @Override
    public int authDataScope(AppDevice device) {
        // 修改设备信息
        appDeviceMapper.updateAppDevice(device);
        // 删除设备与部门关联
        appDeviceMapper.deleteAppDeviceDeptByDeviceId(device.getDeviceId());
        // 新增设备和部门信息（数据权限）
        return insertAppDeviceDept(device);
    }

    @Override
    public void checkDevicePlaceScope(Long deviceId) {
        if (!SysUser.isAdmin(SecurityUtils.getUserId())) {
            AppDevice device = new AppDevice();
            device.setDeviceId(deviceId);
            List<AppDevice> devices = SpringUtils.getAopProxy(this).selectAppDeviceList(device);
            if (StringUtils.isEmpty(devices)) {
                throw new ServiceException("没有权限访问设备数据！");
            }
        }
    }

    @Override
    public int authPlaceScope(AppDevice device) {
        // 修改设备信息
        appDeviceMapper.updateAppDevice(device);
        // 删除设备与部门关联
        appDeviceMapper.deleteAppDevicePlaceByDeviceId(device.getDeviceId());
        // 新增设备和部门信息（数据权限）
        return insertAppDevicePlace(device);
    }

    @Override
    public List<AppDevice> selectAppDeviceAll(AppDevice device) {
        List<AppDevice> list = appDeviceMapper.selectAppDeviceAll(device);
        List<AppDevice> voList = new ArrayList<>();
        for (AppDevice appDevice : list) {
            appDevice.setOperatorIds(new Long[]{});
            appDevice.setAdminIds(new Long[]{});
            appDevice.setOperator(new ArrayList<SysUser>());
            appDevice.setAdmin(new ArrayList<SysUser>());
            if (appDevice.getParentName() == null) {
                appDevice.setParentName("");
            }
            if (appDevice.getRemark() == null) {
                appDevice.setRemark("");
            }
            if (appDevice.getRemark() == null) {
                appDevice.setRemark("");
            }
            appDevice.setDeptIds(new Long[]{});
            appDevice.setPlaceIds(new Long[]{});
            voList.add(appDevice);
        }
        return voList;
    }

    @Override
    public List<AppDevice> selectAppDeviceByDeviceName(String deviceName) {
        return appDeviceMapper.selectAppDeviceByDeviceName(deviceName);
    }

    @Override
    public DeviceDashboardVO getIndexExhaust(Long projectId) {
        AppDevice appDevice = new AppDevice();
        appDevice.setProjectId(projectId);
        long timeTemp = System.currentTimeMillis();
        List<AppDevice> deviceList = appDeviceMapper.selectAppDeviceList(appDevice);
        System.out.println("设备查询时间：" + ((System.currentTimeMillis() - timeTemp) / 1000));
        timeTemp = System.currentTimeMillis();
        Map<Long, AppDevice> funMap = new HashMap<>();
        Map<Long, AppDevice> fumeHoodMap = new HashMap<>();
        //获取气站设备的顶级设备
        Set<Long> gasStationIds = new HashSet<>();
        //气站下的气瓶
        List<AppDevice> gasList = new ArrayList<>();
        //气路
        List<AppDevice> gasLineList = new ArrayList<>();
        List<Long> gasLineIds = new ArrayList<>();
        for (AppDevice device : deviceList) {
            if (device.getDelFlag().equals("0") && device.getSubCount() == 0L && device.getStatus().equals("0")) {
                if (device.getType().equals("3")) {
                    fumeHoodMap.put(device.getDeviceId(), device);
                } else if (device.getType().equals("2")) {
                    funMap.put(device.getDeviceId(), device);
                } else if (device.getType().equals("8")) {
                    gasLineList.add(device);
                    gasLineIds.add(device.getDeviceId());
                }
            }
            if (device.getType().equals("8") && device.getParentId() == 0L) {
                gasStationIds.add(device.getDeviceId());
            }
        }
        for (AppDevice device : deviceList) {
            if (device.getType().equals("8") && gasStationIds.contains(device.getParentId())) {
                gasList.add(device);
            }
        }
        System.out.println("设备处理时间：" + ((System.currentTimeMillis() - timeTemp) / 1000));
        timeTemp = System.currentTimeMillis();
        DeviceDashboardVO vo = new DeviceDashboardVO();
        int runningFun = 0;
        int exceptionFun = 0;
        for (AppDevice funDevice : funMap.values()) {
//            if (funDevice.getIsRunning() != null && funDevice.getIsRunning().equals("1")) {
//                runningFun++;
//            }
            if (funDevice.getIsException() != null && funDevice.getIsException().equals("1")) {
                exceptionFun++;
            }
        }
        System.out.println("风机传DB感器开始时间：" + ((System.currentTimeMillis() - timeTemp) / 1000));
        timeTemp = System.currentTimeMillis();
        List<AppSensor> funSensorList = appSensorMapper.selectAppSensorAllListByDeviceIds(new ArrayList<>(funMap.keySet()));
        System.out.println("风机传感器DB结束时间：" + ((System.currentTimeMillis() - timeTemp) / 1000));
        timeTemp = System.currentTimeMillis();
        for (AppSensor sensor : funSensorList) {
            if (sensor.getSensorType() != null && sensor.getSensorType().equals("22")) {
                if (sensor.getSensorName() != null && sensor.getSensorName().toLowerCase().contains("state")) {
                    Object object = redisTemplate.opsForValue().get(CacheConstants.APP_SENSOR_VALUE_KEY + sensor.getDeviceId() + ":sensorId:" + sensor.getSensorId());
                    if (object != null && !object.toString().isEmpty()) {
                        if (new BigDecimal(object.toString()).compareTo(BigDecimal.ONE) == 0) {
                            runningFun++;
                        }
                    }
                }
            }
        }
        System.out.println("风机处理时间：" + ((System.currentTimeMillis() - timeTemp) / 1000));
        timeTemp = System.currentTimeMillis();
        vo.setTotalFun(funMap.values().size());
        vo.setExceptionFun(exceptionFun);
        vo.setRunningFun(runningFun);
        vo.setNormalFun(funMap.values().size() - exceptionFun);

        vo.setTotalFumeHood(fumeHoodMap.values().size());
        int runningFumeHood = 0;
        int exceptionFumeHood = 0;
        for (AppDevice funDevice : fumeHoodMap.values()) {
            if (funDevice.getIsRunning() != null && funDevice.getIsException().equals("1")) {
                exceptionFumeHood++;
            }
        }
        List<AppSensor> fumeHoodSensorList = appSensorMapper.selectAppSensorAllListByDeviceIds(new ArrayList<>(fumeHoodMap.keySet()));
        for (AppSensor sensor : fumeHoodSensorList) {
            if (sensor.getSensorType() != null && sensor.getSensorType().equals("22")) {
                if (sensor.getSensorName() != null && sensor.getSensorName().toUpperCase().contains("REM") && !sensor.getSensorName().toLowerCase().contains("set")) {
                    Object object = redisTemplate.opsForValue().get(CacheConstants.APP_SENSOR_VALUE_KEY + sensor.getDeviceId() + ":sensorId:" + sensor.getSensorId());
                    if (object != null && !object.toString().isEmpty()) {
                        if (new BigDecimal(object.toString()).compareTo(BigDecimal.ONE) == 0) {
                            runningFumeHood++;
                        }
                    }
                }
            }
        }
        System.out.println("通风柜处理时间：" + ((System.currentTimeMillis() - timeTemp) / 1000));
        timeTemp = System.currentTimeMillis();
        vo.setExceptionFumeHood(exceptionFumeHood);
        vo.setRunningFumeHood(runningFumeHood);
        vo.setNormalFumeHood(fumeHoodMap.values().size() - exceptionFumeHood);
        int runningGasStation = 0;
        int exceptionGasStation = 0;
        int totalGasStation = 0;
        for (AppDevice gasDevice : gasList) {
            if (gasDevice.getDeviceName().contains("气站")) {
                totalGasStation++;
                if (gasDevice.getIsRunning() != null && gasDevice.getIsRunning().equals("1")) {
                    runningGasStation++;
                }
                if (gasDevice.getIsRunning() != null && gasDevice.getIsException().equals("1")) {
                    exceptionGasStation++;
                }
            }
        }
        System.out.println("气站处理时间：" + ((System.currentTimeMillis() - timeTemp) / 1000));
        timeTemp = System.currentTimeMillis();
        vo.setExceptionGasStation(exceptionGasStation);
        vo.setRunningGasStation(runningGasStation);
        vo.setTotalGasStation(totalGasStation);
        //获取气路流量
        //氦气用量
        Integer gasHe = 0;
        //氧气
        Integer gasO2 = 0;
        //氢气
        Integer gasH2 = 0;
        //氩气 Ar
        Integer gasAr = 0;
        //氮气
        Integer gasN2 = 0;
        //乙炔
        Integer gasC2H2 = 0;
        //二氧化碳
        Integer gasCO2 = 0;
        List<AppSensor> list = appSensorMapper.selectAppSensorAllListByDeviceIds(gasLineIds);
        for (AppSensor sensor : list) {
            if (sensor.getSensorType().equals("31")) {
                if (sensor.getSensorName().contains("累计流量")) {
                    int value = 0;
                    String s = null;
                    Object object = redisTemplate.opsForValue().get(CacheConstants.APP_SENSOR_VALUE_KEY + sensor.getDeviceId() + ":sensorId:" + sensor.getSensorId());
                    if (object != null) {
                        if (object instanceof String) {
                            s = object.toString();
                        }
                        if (object instanceof BigDecimal) {
                            s = ((BigDecimal) object).toString();
                        }
                    }
                    if (s != null) {
                        BigDecimal bigDecimal = new BigDecimal(s);
                        value = bigDecimal.intValue();
                    }
                    if (sensor.getSensorName().toLowerCase().contains("he")) {
                        gasHe += value;
                    } else if (sensor.getSensorName().toLowerCase().contains("o2")) {
                        gasO2 += value;
                    } else if (sensor.getSensorName().toLowerCase().contains("h2")) {
                        gasH2 += value;
                    } else if (sensor.getSensorName().toLowerCase().contains("ar")) {
                        gasAr += value;
                    } else if (sensor.getSensorName().toLowerCase().contains("n2")) {
                        gasN2 += value;
                    } else if (sensor.getSensorName().toLowerCase().contains("c2h2")) {
                        gasC2H2 += value;
                    } else if (sensor.getSensorName().toLowerCase().contains("co2")) {
                        gasCO2 += value;
                    }
                }
            }
        }
        System.out.println("气路处理时间：" + ((System.currentTimeMillis() - timeTemp) / 1000));
        vo.setGasHe(gasHe);
        //氧气
        vo.setGasO2(gasO2);

        //氢气
        vo.setGasH2(gasH2);

        //氩气 Ar
        vo.setGasAr(gasAr);

        //氮气
        vo.setGasN2(gasN2);

        //乙炔
        vo.setGasC2H2(gasC2H2);

        //二氧化碳
        vo.setGasCO2(gasCO2);
        return vo;
    }

    @Override
    public List<AppDevice> selectWxDeviceList(SysUser sysUser) {
        AppDevice appDevice = new AppDevice();
        if (sysUser != null && !sysUser.isAdmin()) {
            dataScopeFilter(appDevice, sysUser, "d", "", "");
        }
        List<AppDevice> list = appDeviceMapper.selectWxDeviceList(appDevice);
        return list;
    }

    @Override
    public List<SysPlace> selectDevicePlaceByDeviceId(Long deviceId) {
        return appDeviceMapper.selectDevicePlaceByDeviceId(deviceId);
    }

    @Override
    public List<AppDevice> selectDeviceListByUserId(Long userId) {
        return appDeviceMapper.selectDeviceListByUserId(userId);
    }

    @Override
    public List<Long> selectAdminPhoneByDeviceId(Long deviceId) {
        return appDeviceMapper.selectAdminPhoneByDeviceId(deviceId);
    }

    @Override
    public List<AppDevice> selectDeviceListIsShow() {
        return appDeviceMapper.selectDeviceListIsShow();
    }

    @Override
    public List<AppDevice> selectChildrenAppDeviceById(Long deviceId) {
        List<AppDevice> appDeviceList = appDeviceMapper.selectChildrenAppDeviceById(deviceId);
        selectChildren(appDeviceList);
        return appDeviceList;
    }

    @Override
    public List<AppDevice> selectAppDeviceListSimple(AppDevice appDevice) {
        return appDeviceMapper.selectAppDeviceAll(appDevice);
    }

    @Override
    public List<SysUser> selectUserByDeviceId(Long deviceId, String userType) {
        return appDeviceMapper.selectUserByDeviceId(deviceId, userType);
    }

    @Override
    public AppDevice selectAppDeviceByDeviceCode(String deviceCode) {
        AppDevice device = new AppDevice();
        device.setDeviceCode(deviceCode.trim());
        List<AppDevice> deviceList = appDeviceMapper.selectAppDeviceList(device);
        if (!deviceList.isEmpty()){
            return  deviceList.get(0);
        }
        return null;
    }

    @Override
    public List<AppDevicePlaces> selectAppDevicePlaceListByDeviceIds(List<Long> deviceIds) {
        return devicePlacesMapper.selectAppDevicePlaceListByDeviceIds(deviceIds);
    }


    private void selectChildren(List<AppDevice> list) {
        if (!list.isEmpty()) {
            for (AppDevice device : list) {
                List<AppDevice> children = appDeviceMapper.selectChildrenAppDeviceById(device.getDeviceId());
                device.setChildren(children);
                selectChildren(children);
            }
        }
    }

    /**
     * 新增设备部门信息(数据权限)
     *
     * @param device 设备对象
     */
    public int insertAppDeviceDept(AppDevice device) {
        for (Long deptId : device.getDeptIds()) {
            appDeviceMapper.insertAppDeviceDept(device.getDeviceId(), deptId);
        }
        return 1;
    }


    /**
     * 新增设备部门信息(数据权限)
     *
     * @param device 设备对象
     */
    public int insertAppDevicePlace(AppDevice device) {
        for (Long placeId : device.getPlaceIds()) {
            appDeviceMapper.insertAppDevicePlace(device.getDeviceId(), placeId);
        }
        return 1;
    }

    /**
     * 数据范围过滤
     *
     * @param user       用户
     * @param deptAlias  部门别名
     * @param userAlias  用户别名
     * @param permission 权限字符
     */
    public void dataScopeFilter(AppDevice appDevice, SysUser user, String deptAlias, String userAlias, String permission) {
        StringBuilder sqlString = new StringBuilder();
        List<String> conditions = new ArrayList<String>();

        for (SysRole role : user.getRoles()) {
            String dataScope = role.getDataScope();
            if (deptAlias != null && !deptAlias.equals("")) {
                if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope)) {
                    continue;
                }
                if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions())
                        && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) {
                    continue;
                }
                if (DATA_SCOPE_ALL.equals(dataScope)) {
                    sqlString = new StringBuilder();
                    break;
                } else if (DATA_SCOPE_CUSTOM.equals(dataScope)) {
                    sqlString.append(StringUtils.format(
                            " OR {}.device_id in (select ap.device_id from app_device_depts ap where ap.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ) ", deptAlias,
                            role.getRoleId()));
                } else if (DATA_SCOPE_DEPT.equals(dataScope)) {
                    sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
                } else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) {
                    sqlString.append(StringUtils.format(
                            " OR {}.device_id in (select ap.device_id from app_device_depts ap where ap.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
                            deptAlias, user.getDeptId(), user.getDeptId()));
                } else if (DATA_SCOPE_SELF.equals(dataScope)) {
                    if (StringUtils.isNotBlank(userAlias)) {
                        sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
                    } else {
                        // 数据权限为仅本人且没有userAlias别名不查询任何数据
                        sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
                    }
                }
                conditions.add(dataScope);
            }
        }

        if (StringUtils.isNotBlank(sqlString.toString())) {
            appDevice.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
        }
    }

}
